//
// Created by martin on 2/16/22.
//

#ifndef MUDUO_TCPSERVER_H
#define MUDUO_TCPSERVER_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/Atomic.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/TcpConnection.h"

#include <map>
#include <string>
#include <memory>

namespace muduo
{
namespace net
{

class EventLoop;
class EventLoopThreadPool;
class InetAddress;
class Acceptor;

/**
 * Tcp Server, 支持单线程和thread-poll模型.
 * 接口类, 因此不要暴露太多细节.
 */
class TcpServer : private noncopyable
{
public:
    typedef std::function<void (EventLoop*)> ThreadInitCallback;
    enum Option
    {
        kNoReusePort, // 不允许重用本地端口
        kReusePort,   // 允许重用本地端口
    };

//    TcpServer(EventLoop* loop, const InetAddress& listenAddr);
    TcpServer(EventLoop* loop,
              const InetAddress& listenAddr,
              const std::string& nameArg,
              Option option = kNoReusePort);
    ~TcpServer(); // force out-line dtor, for std::unique_ptr members.

    const std::string& ipPort() const { return ipPort_; }
    const std::string& name() const { return name_; }
    EventLoop* getLoop() const { return loop_; }

    /**
     * 设置处理输入的线程数量.
     * @note 一直在loop线程中接受新连接. 必须在start()前调用
     * @param numThreads 线程数量, 每个线程都是一个loop线程
     */
    void setThreadNum(int numThreads);

    /**
     * 设置线程初始回调, 在线程函数启动后, 进入loop循环前调用
     */
    void setThreadInitCallback(const ThreadInitCallback& cb)
    { threadInitCallback_ = cb; }

    /*　返回线程池指针, shared_ptr管理　*/
    std::shared_ptr<EventLoopThreadPool> threadPool()
    { return threadPool_; }

    /**
     * 如果没有监听, 就启动服务器(监听).
     * @note 多次调用没有副作用.
     * 线程安全.
     */
    void start();

    /**
     * 设置连接回调.
     * 非线程安全.
     */
    void setConnectionCallback(const ConnectionCallback& cb)
    { connectionCallback_ = cb; }

    /**
     * 设置消息回调.
     * 非线程安全.
     */
    void setMessageCallback(const MessageCallback & cb)
    { messageCallback_ = cb; }

    /**
     * 设置写完成回调.
     * 非线程安全.
     */
    void setWriteCompleteCallback(const WriteCompleteCallback& cb)
    { writeCompleteCallback_ = cb; }

private:
    /**
     * 新建连接, 会用sockfd和对端ip地址, 来新建一个TcpConnection对象
     * 非线程安全, 但只在loop线程中运行　
     */
    void newConnection(int sockfd, const InetAddress& peerAddr);
    /**
     * 移除连接, 内部删除连接conn
     * 线程安全.
     */
    void removeConnection(const TcpConnectionPtr& conn);
    /**
     * Not Thread safe, but in loop
     */

    /**
     * 新建连接, 会用sockfd和对端ip地址, 来新建一个TcpConnection对象
     * 非线程安全, 但只在loop线程中运行　
     */
    void removeConnectionInLoop(const TcpConnectionPtr& conn);

    typedef std::map<std::string, TcpConnectionPtr> ConnectionMap;

    EventLoop* loop_; // the acceptor loop
    const std::string ipPort_; // IP地址及端口号字符串
    const std::string name_;   // 名称
    std::unique_ptr<Acceptor> acceptor_;  // 接受器 // avoid revealing Acceptor
    std::shared_ptr<EventLoopThreadPool> threadPool_;  // 线程池
    ConnectionCallback connectionCallback_;            // 连接回调
    MessageCallback messageCallback_;                  // 消息回调
    WriteCompleteCallback writeCompleteCallback_;      // 写完成回调
    ThreadInitCallback threadInitCallback_;            // 线程初始回调
    AtomicInt32 started_;                              // (服务器)启动标志
    // always in loop thread, thread safe is no need
    int nextConnId_;            // 连接id
    ConnectionMap connections_; // 存放连接对象的std::map
};

} // namespace net
} // namespace muduo

#endif //MUDUO_TCPSERVER_H
